package com.zheng.oss.admin.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.zheng.common.base.BaseController;
import com.zheng.common.util.Pagination;
import com.zheng.oss.common.constant.OssResult;
import com.zheng.oss.common.constant.OssResultConstant;
import com.zheng.oss.common.constant.enums.FilePermission;
import com.zheng.oss.dao.model.OssFile;
import com.zheng.oss.dao.model.OssFileStack;
import com.zheng.oss.dao.model.OssRoleFile;
import com.zheng.oss.dto.FileInfo;
import com.zheng.oss.dto.FolderDto;
import com.zheng.oss.rpc.api.OssFileService;
import com.zheng.oss.rpc.api.OssFileStackService;
import com.zheng.oss.rpc.api.OssRoleFileService;
import com.zheng.oss.web.controller.FastDFSController;
import com.zheng.oss.web.util.FastDFSFile;
import com.zheng.oss.web.util.FileManager;
import com.zheng.oss.web.util.UploadResult;
import com.zheng.upms.dao.model.UpmsRole;
import com.zheng.upms.dao.model.UpmsUser;
import com.zheng.upms.rpc.api.UpmsApiService;
import com.zheng.upms.rpc.api.UpmsRoleService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.csource.common.NameValuePair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;

/**
 * Created by likun on 2018/4/29.
 */
@Controller
@Api(value = "系统文件管理", description = "系统文件管理")
@RequestMapping("/manage/oss/file/system")
public class SystemFileController extends BaseController {
    @Autowired
    private OssFileService fileService;
    @Autowired
    private UpmsApiService apiService;
    @Autowired
    private UpmsRoleService roleService;
    @Autowired
    private OssFileStackService fileStackService;
    @Autowired
    private OssRoleFileService roleFileService;
    private final int systemRootId = 1;
    private final int personalRootId = 2;
    private final int adminRoleId = 1;

    @ApiOperation(value = "文档首页")
    @RequiresPermissions("oss:file:system")
    @RequestMapping(value = "/index", method = RequestMethod.GET)
    public String index(Model model) {
        model.addAttribute("folderId", systemRootId);
        model.addAttribute("folderType", OssFile.FOLDER_TYPE);
        return "/manage/system/index.jsp";
    }

    @ApiOperation(value = "文件列表")
    @RequiresPermissions("oss:file:system")
    @ResponseBody
    @RequestMapping(value = "/list", method = RequestMethod.GET)
    public Object list(@RequestParam(required = false, defaultValue = "1", value = "pageNumber") int pageNumber,
                       @RequestParam(required = false, defaultValue = "20", value = "pageSize") int pageSize,
                       @RequestParam(required = false, value = "sortName") String sortName,
                       @RequestParam(required = false, value = "sortOrder") String sortOrder,
                       OssFile file) {
        UpmsUser upmsUser = apiService.selectUpmsUserByUsername(getUsername());
        List<UpmsRole> roles = apiService.selectUpmsRoleByUpmsUserIdByCache(upmsUser.getUserId());
        List<Integer> roleIds = new ArrayList<>();
        roles.forEach(role -> roleIds.add(role.getRoleId()));
        file.setRoleIds(roleIds);
        file.setPermission(FilePermission.VIEW.getKey());
        file.setPagination(new Pagination(pageNumber, pageSize, sortOrder, sortName));
        file.setStatus(OssFile.NORMAL_STATUS);
        if (file.getId() == null) {
            file.setId(systemRootId);
        }
        List<Map<String, Object>> rows = fileService.selectFilePage(file);
        Integer total = fileService.selectFilePageCount(file);
        Map<String, Object> result = new HashMap<>();
        result.put("rows", rows);
        result.put("total", total);
        return result;
    }

    @ApiOperation(value = "文件夹列表")
    @RequiresPermissions("oss:file:system")
    @ResponseBody
    @RequestMapping(value = "/folderList", method = RequestMethod.GET)
    public Object folderList(Integer checkedNodeId, Integer id) {
        OssFile ossFile = new OssFile();
        UpmsUser upmsUser = apiService.selectUpmsUserByUsername(getUsername());
        List<UpmsRole> roles = apiService.selectUpmsRoleByUpmsUserIdByCache(upmsUser.getUserId());
        List<Integer> roleIds = new ArrayList<>();
        roles.forEach(role -> roleIds.add(role.getRoleId()));
        ossFile.setRoleIds(roleIds);
        ossFile.setPermission(FilePermission.VIEW.getKey());
        ossFile.setFileType(OssFile.FOLDER_TYPE);
        ossFile.setStatus(OssFile.NORMAL_STATUS);
        ossFile.setPath("'%," + systemRootId + ",%'");
        if (id == null) {
            ossFile.setId(systemRootId);
        }
        List<OssFile> ossFiles = fileService.selectFileTree(ossFile);
        JSONArray treeArray = new JSONArray();
        for (OssFile file : ossFiles) {
            boolean hasParent = false;
            Integer pid = file.getPid();
            //查找是否有当前节点的父节点，没有就不加进来
            for (OssFile pFile : ossFiles) {
                if (pFile.getId().equals(pid) || systemRootId == pid) {
                    hasParent = true;
                    break;
                }
            }
            if (!hasParent && !file.getId().equals(systemRootId)) {
                continue;
            }
            JSONObject treeNode = new JSONObject();
            treeNode.put("id", file.getId());
            treeNode.put("pId", pid);
            treeNode.put("name", file.getFilename());
            treeNode.put("open", true);
            if (checkedNodeId != null && checkedNodeId.equals(file.getId())) {
                treeNode.put("open", true);
            }
            treeArray.add(treeNode);
        }
        return treeArray;
    }

    @RequiresPermissions("oss:file:system")
    @RequestMapping(value = "/update", method = RequestMethod.GET)
    public String update(Model model, Integer id) {
        OssFile file = fileService.selectById(id);
        model.addAttribute("file", file);
        model.addAttribute("folderPath", getFolderPath(file.getPid()) + file.getFilename());
        return "/manage/system/update.jsp";
    }

    @RequiresPermissions("oss:file:system")
    @RequestMapping(value = "/update", method = RequestMethod.POST)
    @ResponseBody
    public Object update(OssFile file) {
        try {
            fileService.updateSystemFile(file, getUsername());
        } catch (Exception e) {
            return new OssResult(OssResultConstant.FAILED, e.getMessage());
        }
        return new OssResult(OssResultConstant.SUCCESS, null);
    }

    @RequiresPermissions("oss:file:system")
    @RequestMapping(value = "/upload", method = RequestMethod.GET)
    public String upload(Model model, Integer folderId) {
        //获取文件层级
        String folderPath = getFolderPath(folderId);
        //获取文件权限类型
        JSONArray filePermissions = FilePermission.getAll();
        model.addAttribute("folderId", folderId);
        model.addAttribute("folderPath", folderPath);
        model.addAttribute("filePermissions", filePermissions);

        return "/manage/system/upload.jsp";
    }

    @RequiresPermissions("oss:file:system")
    @RequestMapping(value = "/createFolder", method = RequestMethod.GET)
    public String createFolder(Model model, Integer folderId) {
        //获取文件层级
        String folderPath = getFolderPath(folderId);
        //获取文件权限类型
        JSONArray filePermissions = FilePermission.getAll();
        List<UpmsRole> roles = roleService.selectList(null);

        model.addAttribute("folderId", folderId);
        model.addAttribute("folderPath", folderPath);
        model.addAttribute("filePermissions", filePermissions);
        model.addAttribute("roles", roles);
        return "/manage/system/createFolder.jsp";
    }

    private String getFolderPath(Integer pid) {
        StringBuilder sb = new StringBuilder("");
        OssFile pFile = fileService.selectById(pid);
        String[] ids = pFile.getPath().split(",");
        List<Integer> idList = new ArrayList<>();
        for (String idStr : ids) {
            idList.add(Integer.parseInt(idStr));
        }
        EntityWrapper<OssFile> fileEntityWrapper = new EntityWrapper<>();
        fileEntityWrapper.in("id", idList).or().eq("id", pid);
        List<OssFile> fileList = fileService.selectList(fileEntityWrapper);
        //判断第一个file的path中所含父id是否多于后一个file
       /* Collections.sort(fileList, (o1, o2) ->
                o1.getPath().split(",").length - o2.getPath().split(",").length);*/
        for (OssFile file : fileList) {
            sb.append(file.getFilename());
            sb.append("/");
        }
        return sb.toString();
    }

    @RequiresPermissions("oss:file:system")
    @ResponseBody
    @RequestMapping(value = "/createFolder", method = RequestMethod.POST)
    public Object createFolder(FolderDto folder) {
        try {
            fileService.createFolder(folder, getUsername());
        } catch (Exception e) {
            return new OssResult(OssResultConstant.FAILED, e.getMessage());
        }
        return new OssResult(OssResultConstant.SUCCESS, null);
    }

    @RequiresPermissions("oss:file:system:permission")
    @RequestMapping(value = "/filePermission", method = RequestMethod.GET)
    public String filePermission(Integer fileId, Model model) {
        List<Map<String, Object>> roleFiles = roleFileService.selectRoleFile(fileId, adminRoleId);
        List<UpmsRole> roles = roleService.selectList(new EntityWrapper<UpmsRole>().notIn("role_id", adminRoleId));
        JSONArray filePermissions = FilePermission.getAll();
        for (UpmsRole role : roles) {
            boolean flag = true;
            for (Map<String, Object> roleFile : roleFiles) {
                if (role.getRoleId().equals(Integer.parseInt(roleFile.get("roleId").toString()))) {
                    flag = false;
                    break;
                }
            }
            if (flag) {
                Map<String, Object> roleFile = new HashMap<>();
                roleFile.put("title", role.getTitle());
                roleFile.put("roleId", role.getRoleId());
                roleFile.put("fileId", fileId);
                roleFile.put("permission", FilePermission.VIEW.getKey());
                roleFiles.add(roleFile);
            }
        }
        model.addAttribute("roles", roles);
        model.addAttribute("filePermissions", filePermissions);
        model.addAttribute("fileId", fileId);
        model.addAttribute("roleFiles", JSONObject.toJSON(roleFiles));
        return "/manage/system/filePermission.jsp";
    }

    @RequiresPermissions("oss:file:system:permission")
    @ResponseBody
    @RequestMapping(value = "/filePermission", method = RequestMethod.POST)
    public Object filePermission(@RequestBody JSONObject param) {
        List<OssRoleFile> roleFiles = param.getJSONArray("roleFiles").toJavaList(OssRoleFile.class);
        Boolean effect = param.getBoolean("effect");
        try {
            roleFileService.filePermission(roleFiles, effect);
        } catch (Exception e) {
            return new OssResult(OssResultConstant.FAILED, null);
        }
        return new OssResult(OssResultConstant.SUCCESS, null);

    }

    @RequestMapping(value = "/fileUpload", method = RequestMethod.POST)
    @ResponseBody
    public Object fileUpload(@RequestParam(value = "file", required = true) MultipartFile file,
                             FileInfo fileInfo) {
        UpmsUser user = apiService.selectUpmsUserByUsername(getUsername());
        Integer pid = fileInfo.getPid();
        String fileName = fileInfo.getFilename();
        EntityWrapper<OssFile> fileEntityWrapper = new EntityWrapper<>();
        fileEntityWrapper.eq("pid", pid).eq("filename", fileName).eq("status", OssFile.NORMAL_STATUS);
        if (fileService.selectCount(fileEntityWrapper) > 0) {
            return new OssResult(OssResultConstant.FAILED, "当前目录下已有同名文件！");
        }
        OssFile pOssFile = fileService.selectById(pid);
        if (pOssFile == null) {
            return new OssResult(OssResultConstant.FAILED, "当前上传的文件目录不存在！,请更换目录！");
        }
        //判断是否为系统文件
        if (pOssFile.getId().equals(systemRootId) || pOssFile.getPath().contains("," + systemRootId + ",")) {
            //查找当前用户的所有角色
            List<UpmsRole> roles = apiService.selectUpmsRoleByUpmsUserIdByCache(user.getUserId());
            List<Integer> roleIds = new ArrayList<>();
            roles.forEach(role -> roleIds.add(role.getRoleId()));
            //获取该文件是否有权限
            EntityWrapper<OssRoleFile> roleFileEntityWrapper = new EntityWrapper<>();
            roleFileEntityWrapper.eq("file_id", pid).in("role_id", roleIds).and("permission >=" + FilePermission.UPDATE.getKey());
            int count = roleFileService.selectCount(roleFileEntityWrapper);
            if (count < 1) {
                return new OssResult(OssResultConstant.FAILED, "当前用户没有操作当前文件、文件夹的权限！");
            }
        }
        String ext = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1);
        UploadResult upload = FileManager.upload(file);
        if (null == upload) {
            _log.error("上传文件" + file.getOriginalFilename() + "失败！");
            //上传失败
            return new OssResult(OssResultConstant.FAILED, "上传失败！");
        }
        String group = upload.getGroupName();
        String fileRealPath = upload.getFileAbsolutePath();
        OssFileStack fileStack = new OssFileStack();
        fileStack.setSize(file.getSize());
        fileStack.setExt(ext);
        fileStack.setUrl(fileRealPath);
        JSONObject otherInfo = new JSONObject();
        otherInfo.put("group", group);
        otherInfo.put("remoteFileName", upload.getRemoteFileName());
        fileStack.setOtherInfo(otherInfo.toJSONString());
        try {
            fileStack = fileStackService.insertFileStack(fileStack);
        } catch (Exception e) {
            //添加堆文件失败，就直接删除已经上传的文件
            try {
                FileManager.delete(group, fileRealPath);
            } catch (Exception e1) {
                _log.error(upload.toString() + "创建失败后删除失败！");
            }
            return new OssResult(OssResultConstant.FAILED, "上传失败！");
        }
        OssFile ossFile = new OssFile();
        ossFile.setFileStackId(fileStack.getId());
        ossFile.setPid(pid);
        ossFile.setFileType(OssFile.FILE_TYPE);
        ossFile.setCuser(user.getUserId());
        ossFile.setCorganization(user.getOrganizationId());
        ossFile.setCtime(new Date());
        ossFile.setPath(pOssFile.getPath() + pOssFile.getId() + ",");
        ossFile.setFilename(fileName);
        ossFile.setStatus(OssFile.NORMAL_STATUS);
        try {
            ossFile = fileService.insertFile(ossFile);
            roleFileService.insertRoleFile(ossFile);
        } catch (Exception e) {
            //添加文件目录失败，也算上传成功，但是返回失败信息
            _log.error("添加文件目录" + ossFile.getFilename() + "失败！" + e);
            return new OssResult(OssResultConstant.FAILED, "上传失败！");
        }
        return new OssResult(OssResultConstant.SUCCESS, "上传成功！");
    }
}
